﻿using Newtonsoft.Json;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.Extensions.Caching.Distributed
{
    public static class IDistributedCacheExtensions
    {

        ///// <summary>
        ///// 获取缓存，反序列化成对象返回
        ///// </summary>
        ///// <param name="cache"></param>
        ///// <param name="key">key</param>
        ///// <returns>对象</returns>
        //public static object GetObject(this IDistributedCache cache, string key)
        //{
        //    return Deserialize(cache.Get(key));
        //}
        /// <summary>
        /// 获取缓存，反序列化成对象返回
        /// </summary>
        /// <typeparam name="T">反序列化类型</typeparam>
        /// <param name="cache"></param>
        /// <param name="key">key</param>
        /// <returns>对象</returns>
        public static T GetObject<T>(this IDistributedCache cache, string key)
        {
            var obj = Deserialize<T>(cache.Get(key));
            if (obj == null) return default(T);
            return (T)obj;
        }
        ///// <summary>
        ///// 获取缓存，反序列化成对象
        ///// </summary>
        ///// <param name="cache"></param>
        ///// <param name="key">key</param>
        ///// <returns>对象</returns>
        //async public static Task<object> GetObjectAsync(this IDistributedCache cache, string key)
        //{
        //    return Deserialize(await cache.GetAsync(key));
        //}
        /// <summary>
        /// 获取缓存，反序列化成对象
        /// </summary>
        /// <typeparam name="T">反序列化类型</typeparam>
        /// <param name="cache"></param>
        /// <param name="key">key</param>
        /// <returns>对象</returns>
        async public static Task<T> GetObjectAsync<T>(this IDistributedCache cache, string key)
        {
            var obj = Deserialize<T>(await cache.GetAsync(key));
            if (obj == null) return default(T);
            return obj;
        }
        /// <summary>
        /// 序列化对象后，设置缓存
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="key">key</param>
        /// <param name="value">对象</param>
        public static void SetObject(this IDistributedCache cache, string key, object value)
        {
            var data = Serialize(value);
            if (data == null) cache.Remove(key);
            else cache.Set(key, Serialize(value));
        }
        /// <summary>
        /// 序列化对象后，设置缓存
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="key">key</param>
        /// <param name="value">对象</param>
        /// <param name="options">策略</param>
        public static void SetObject(this IDistributedCache cache, string key, object value, DistributedCacheEntryOptions options)
        {
            var data = Serialize(value);
            if (data == null) cache.Remove(key);
            else cache.Set(key, Serialize(value), options);
        }
        /// <summary>
        /// 序列化对象后，设置缓存
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="key">key</param>
        /// <param name="value">对象</param>
        public static Task SetObjectAsync(this IDistributedCache cache, string key, object value)
        {
            var data = Serialize(value);
            if (data == null) return cache.RemoveAsync(key);
            else return cache.SetAsync(key, Serialize(value));
        }
        /// <summary>
        /// 序列化对象后，设置缓存
        /// </summary>
        /// <param name="cache"></param>
        /// <param name="key">key</param>
        /// <param name="value">对象</param>
        /// <param name="options">策略</param>
        public static Task SetObjectAsync(this IDistributedCache cache, string key, object value, DistributedCacheEntryOptions options)
        {
            var data = Serialize(value);
            if (data == null) return cache.RemoveAsync(key);
            else return cache.SetAsync(key, Serialize(value), options);
        }

        public static byte[] Serialize(object value)
        {
            if (value == null) return null;
            var str = JsonConvert.SerializeObject(value);
            return Encoding.UTF8.GetBytes(str);
        }
        public static T Deserialize<T>(byte[] stream)
        {
            if (stream == null) return default(T);
            try
            {
              var str =   Encoding.UTF8.GetString(stream);
               return JsonConvert.DeserializeObject<T>(str);
            }
            catch (Exception)
            {

                return default(T);
            }

        }
    }
}
